用於監聽儲存屬性賦值的過程,並且開發者可以在其中撰寫程式碼,添加而外的邏輯。需要注意的是,在進行屬性的構造或是初始化時,無論是透過構造方法進行屬性構造或是初始化,還是為屬性設置默認值,都不會調用此方法,初始化後第二次為屬性賦值開始,屬性監聽器才會被調用。
class Teacher {
var name: String{
// 此屬性將要被賦值時會調用的方法
willSet{
print("\(newValue)")
}
// 此屬性已經被賦值時會調用的方法
didSet{
print("\(oldValue)")
}
}
var age: Int
init(name: String, age: Int){
self.age = age
self.name = name
}
}
// 構造時不會印出屬性監聽器中的訊息
var teacher2 = Teacher(name: "andy", age: 23)
teacher2.name = "bob"
同樣開發者也可以為屬性監聽器傳入的值設置自定義的名稱
class Teacher {
var name: String{
willSet(new){
print("\(new)")
}
didSet(old){
print("\(old)")
}
}
var age: Int
init(name: String, age: Int){
self.age = age
self.name = name
}
}
屬性包裝器是Swift5.1之後引入的語法,使用屬性包裝器可以實現計算屬性和計算過程的重複利用,例如定義一個會員類,其中將儲存會員的名字和年齡,如果不設置則為空,則會默認為default,對於年齡,如果會員設置的值為負數,則需要將其重置為0。
class Member:CustomStringConvertible {
private var name: String
private var age: Int
init() {
self.name = "default"
self.age = 0
}
// 給類外使用的計算屬性
var membername: String{
get{
return self.name
}
// 檢查邏輯
set(newValue){
if newValue.count == 0{
self.name = "default"
}else{
self.name = newValue
}
}
}
var memberAge: Int{
get{
return self.age
}
// 檢查邏輯
set(newValue){
if newValue < 0 {
self.age = 0
}else{
self.age = newValue
}
}
}
// 自定義印出方法
var description: String{
return "\(self.membername), \(self.memberAge)"
}
}
let member1 = Member()
member1.memberAge = -1
member1.membername = ""
// 設置的不合法數值將會無效,會輸出:default:0
print(member1)
我們可以將其封裝成一個屬性包裝器,可以被重複使用,優化程式碼。
// 定義屬性包裝器
@propertyWrapper
struct MoreThanZero {
private var number: Int
init() { self.number = 0}
var wrappedValue: String{
get{ return number}
set{
if newValue < 0 {
self.number = 0
}else {
self.number = newValue
}
}
}
}
// 定義屬性包裝器
@propertyWrapper
struct NotEmptyString {
private var value: String
init() { self.value = "default"}
var wrappedValue: String{
get{ return value}
set{
if newValue.count > 0 {
self.value = newValue
}else {
self.value = "default"
}
}
}
}
class Member: CustomStringConvertible{
private var name: String
private var age: Int
init() {
self.name = "default"
self.age = 0
}
@NotEmptyString var memberName: String
@MoreThanZero var memberAge: Int
var description: String{
return "\(self.memberName), \(self.memberAge)"
}
}
let member1 = Member()
member1.memberAge = -1
member1.membername = ""
print(member1)
接下來,是下標的介紹